<?php

namespace App\Service\CallingCards;

use App\Models\FeishuCallingCard\FeishuCallingCard;
use App\Models\FeishuCallingCard\FeishuCallingCardPosterBackground;
use App\Service\Common\OssService;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use Kuafu\File\FileUtil;

class ShareImageService
{
    const FILE_NAME_PREFIX = 'kuafu_tiger_calling_cards_';

    // 默认背景图
    const DEFAULT_BG = 'bb/e8/6b6c51ee73bc8dbdd92d6ea463eed97157b3465c75bd6050777a19188375.png';
    // 透明图层
    const BG0 = 'f5/6a/f0763449e2c1f38fe91c9af8759def1eccacb9cdc8a1dbca7e99400be997.png';
    const FX = 'f5/6a/f0763449e2c1f38fe91c9af8759def1eccacb9cdc8a1dbca7e99400be997.png';
    // 字体，苹方
    const FONT = '96/ec/2276d8e77453e0e44f1e9633ee513396f2eeabb3d330f9e9306343b25fd9.ttf';

    protected static ?string $userAvatarLocalFile = null;
    protected static ?string $userShareLocalFile  = null;
    protected static ?string $bgUrl               = null;
    protected static int     $bgHeight            = 1086;

    /**
     * 制作分享图，并且返回oss的url
     * @param FeishuCallingCard $callingCard
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public static function shareImage(FeishuCallingCard $callingCard): array
    {
        ini_set('memory_limit','2048M');
        static::prepareResource($callingCard);
        $tmpFile = static::makeImage($callingCard);
        $arr = OssService::uploadFile($tmpFile);
        @unlink($tmpFile);
        @unlink(static::$userAvatarLocalFile);
        @unlink(static::$userShareLocalFile);
        return $arr;
    }

    public static function updateBackgroundReview(FeishuCallingCardPosterBackground $background)
    {
        if (!strlen($background->imageUrl)) {
            return;
        }

        if (!self::checkSha256('fx', static::FX)) {
            self::downloadFile(static::FX, static::tempFileName('fx'));
        }

        // 下载背景图片文件
        $bgTmpFile = sys_get_temp_dir() . '/' . Str::random(10);
        static::downloadFile($background->imageUrl, $bgTmpFile);
        $bgHeight = Image::make($bgTmpFile)->height();
        // 合成
        $tmpFIle = sys_get_temp_dir() . '/' . Str::random(10) . '.jpg';
        Image::canvas(750, $bgHeight + 248)
            ->insert($bgTmpFile)
            ->insert(static::tempFileName('fx'), 'top-left', 0, $bgHeight + 248 - 356)
            ->save($tmpFIle);
        $arr = OssService::uploadFile($tmpFIle, '.jpg');
        $background->previewImageUrl = $arr['path'] ?? '';
        @unlink($bgTmpFile);
        @unlink($tmpFIle);
    }

    /**
     * 生成图片
     * @param \App\Models\FeishuCallingCard\FeishuCallingCard $callingCard
     * @return string
     */
    protected static function makeImage(FeishuCallingCard $callingCard)
    {
        $tmpFile = sys_get_temp_dir() . '/' . Str::random(10) . '.jpg';
        $image = Image::canvas(750, static::$bgHeight + 248)
            ->insert(static::tempFileName('bg' . $callingCard->backgroundId))
            ->insert(static::$userAvatarLocalFile, 'top-left', 40, static::$bgHeight - 182 + 248)
            ->insert(static::tempFileName('fx'), 'top-left', 0, static::$bgHeight + 248 - 356)
            ->text($callingCard->name, 156, static::$bgHeight - 142 + 248, function ($font) {
                $font->file(static::tempFileName('font'));
                $font->size(32);
                $font->color('#3A3A3A');
            })
            ->text($callingCard->mobile, 156, static::$bgHeight - 96 + 248, function ($font) {
                $font->file(static::tempFileName('font'));
                $font->size(26);
                $font->color('#979797');
            });
        if ($callingCard->showPosition) {
            $image->text($callingCard->position, 156, static::$bgHeight - 56 + 248, function ($font) {
                $font->file(static::tempFileName('font'));
                $font->size(26);
                $font->color('#979797');
            });
        }
        $image->insert(static::$userShareLocalFile, 'top-left', 456, static::$bgHeight + 248 - 338)
            ->save($tmpFile);
        return $tmpFile;
    }

    /**
     * 固定的文件在本地的临时地址
     * @param $name
     * @return string
     */
    protected static function tempFileName($name): string
    {
        return sys_get_temp_dir() . '/' . static::FILE_NAME_PREFIX . $name;
    }

    /**
     * 准备好资源图片
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    protected static function prepareResource(FeishuCallingCard $callingCard)
    {
        $b = FeishuCallingCardPosterBackground::find($callingCard->backgroundId);
        if (null === $b) {
            static::$bgUrl = static::DEFAULT_BG;
        } else {
            if (!strlen($b->imageUrl)) {
                static::$bgUrl = static::DEFAULT_BG;
            } else {
                static::$bgUrl = $b->imageUrl;
            }
        }
        // 下载图片素材
        if (!self::checkSha256('bg' . $callingCard->backgroundId, static::$bgUrl)) {
            self::downloadFile(static::$bgUrl, static::tempFileName('bg' . $callingCard->backgroundId));
        }
        if (!self::checkSha256('fx', static::FX)) {
            self::downloadFile(static::FX, static::tempFileName('fx'));
        }
        if (!self::checkSha256('font', static::FONT)) {
            self::downloadFile(static::FONT, static::tempFileName('font'));
        }
        // 计算背景图片高度
        static::$bgHeight = Image::make(static::tempFileName('bg' . $callingCard->backgroundId))
            ->height();
        // 下载用户头像
        static::$userAvatarLocalFile = sys_get_temp_dir() . '/' . Str::random(10);
        self::downloadFile($callingCard->avatar, static::$userAvatarLocalFile);
        Image::make(static::$userAvatarLocalFile)->resize(92, 92)->save(static::$userAvatarLocalFile);
        // 下载用户分享用微信小程序二维码，透明的
        static::$userShareLocalFile = sys_get_temp_dir() . '/' . Str::random(10);
        self::downloadFile($callingCard->originalCode, static::$userShareLocalFile);
        Image::make(static::$userShareLocalFile)->resize(248, 248)->save(static::$userShareLocalFile);
    }

    /**
     * 下载oss文件到本地
     * @param string $path
     * @param string $localPath
     * @return void
     */
    protected static function downloadFile(string $path, string $localPath)
    {
        @unlink($localPath);
        file_put_contents($localPath, file_get_contents(FileUtil::domain() . '/' . $path));
    }

    /**
     * 检查文件指纹
     * @param $name
     * @param $url
     * @return bool
     */
    protected static function checkSha256($name, $url): bool
    {
        $tempFilename = static::tempFileName($name);
        if (!is_readable($tempFilename)) {
            return false;
        }
        $sha256 = substr(str_replace('/', '', $url), 0, 64);
        if ($sha256 != hash_file('sha256', $tempFilename)) {
            return false;
        }
        return true;
    }
}
